﻿namespace UnityEditor
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    [Serializable]
    internal class AnimationSelection
    {
        private Hashtable m_AnimatedCurves;
        private int m_AnimatedObjectIndex;
        private GameObject[] m_AnimatedOptions;
        private Hashtable m_AnimatedPaths;
        private AnimationWindow m_AnimationWindow;
        private AnimationClip m_Clip;
        private bool m_ClipCanceled;
        private AnimationPropertyDiff.PropertyState[] m_LastSampledState;
        private Hashtable m_LeftoverCurves;
        private FoldoutTree[] m_Trees = new FoldoutTree[0];

        public AnimationSelection(GameObject[] animatedOptions, SerializedStringTable chosenAnimated, SerializedStringTable chosenClip, AnimationWindow editor)
        {
            this.m_AnimationWindow = editor;
            this.m_AnimatedOptions = animatedOptions;
            string stringArrayHashCode = GetStringArrayHashCode(this.GetAnimatedObjectNames());
            if (!chosenAnimated.Contains(stringArrayHashCode))
            {
                chosenAnimated.Set(stringArrayHashCode, animatedOptions.Length - 1);
            }
            this.m_AnimatedObjectIndex = chosenAnimated.Get(stringArrayHashCode);
            this.RefreshChosenClip(chosenClip);
        }

        public void AddTree(FoldoutTree tree)
        {
            Array.Resize<FoldoutTree>(ref this.m_Trees, this.m_Trees.Length + 1);
            this.trees[this.trees.Length - 1] = tree;
        }

        public bool AutoRecord()
        {
            bool flag = false;
            AnimationPropertyDiff.PropertyState[] rhs = AnimationPropertyDiff.ExtractCurrentState(this.animatedObject);
            AnimationPropertyDiff.PropertyState[] modified = AnimationPropertyDiff.CompareState(this.m_LastSampledState, rhs);
            if ((modified != null) && (modified.Length != 0))
            {
                flag |= AnimationPropertyDiff.RecordModifiedProperties(modified, this.animatedObject, this.clip, this.m_AnimationWindow.time, this.m_AnimationWindow.timeFloor, this.m_AnimationWindow.timeCeiling);
            }
            return flag;
        }

        private bool CheckIfPropertyExists(AnimationClipCurveData data)
        {
            GameObject animatedObject = this.animatedObject;
            if (data.path != string.Empty)
            {
                Transform transform = this.animatedObject.transform.Find(data.path);
                if (transform == null)
                {
                    return false;
                }
                animatedObject = transform.gameObject;
            }
            foreach (UnityEngine.Object obj3 in AnimationUtility.GetAnimatableObjects(animatedObject))
            {
                if (obj3.GetType() == data.type)
                {
                    foreach (AnimationClipCurveData data2 in AnimationUtility.GetAnimatablePropertiesForObject(obj3, animatedObject))
                    {
                        if (data2.propertyName == data.propertyName)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        private void ChooseClip(AnimationClip newClip, int newClipIndex)
        {
            this.m_Clip = newClip;
            this.m_AnimationWindow.chosenClip.Set(GetStringArrayHashCode(this.GetClipNames()), newClipIndex);
        }

        private AnimationClip CreateNewClip(ref int newClipIndex)
        {
            if (!this.EnsureAnimationComponent())
            {
                return null;
            }
            string message = string.Format("Create a new animation for the game object '{0}':", this.animatedObject.name);
            string path = EditorUtility.SaveFilePanelInProject("Create New Animation", "New Animation", "anim", message);
            if (path == string.Empty)
            {
                return null;
            }
            AnimationClip asset = new AnimationClip();
            AssetDatabase.CreateAsset(asset, path);
            this.m_AnimationWindow.EndAnimationMode();
            if (!this.hasAnimationComponent)
            {
                Animation animation = this.animatedObject.AddComponent(typeof(Animation)) as Animation;
                animation.clip = asset;
            }
            AnimationClip[] animationClips = AnimationUtility.GetAnimationClips(this.animatedObject.animation);
            if (animationClips.Length == 0)
            {
                this.animatedObject.animation.playAutomatically = true;
            }
            if ((newClipIndex >= animationClips.Length) || (newClipIndex < 0))
            {
                Array.Resize<AnimationClip>(ref animationClips, animationClips.Length + 1);
                newClipIndex = animationClips.Length - 1;
            }
            animationClips[newClipIndex] = asset;
            AnimationUtility.SetAnimationClips(this.animatedObject.animation, animationClips);
            return asset;
        }

        public void DrawRightIcon(Texture image, Color color, float width)
        {
            Color color2 = GUI.color;
            GUI.color = color;
            Rect iconRect = this.m_AnimationWindow.GetIconRect(width);
            iconRect.width = image.width;
            GUI.DrawTexture(iconRect, image, ScaleMode.ScaleToFit, true, 1f);
            GUI.color = color2;
        }

        private bool EnsureAnimationComponent()
        {
            if (this.hasAnimationComponent)
            {
                return true;
            }
            string warning = string.Format("Editing the animation on the game object '{0}' requires an Animation component. This will break the prefab connection of '{0}'. Do you want to add an animation component to the game object?", this.animatedObject.name);
            return EditorUtility.WarnPrefab(this.animatedObject, "Add Animation Component", warning, "Add component");
        }

        public bool EnsureClipPresence()
        {
            if (this.clip == null)
            {
                if (this.m_ClipCanceled)
                {
                    return false;
                }
                int newClipIndex = -1;
                AnimationClip newClip = this.CreateNewClip(ref newClipIndex);
                if (newClip == null)
                {
                    this.m_ClipCanceled = true;
                    return false;
                }
                this.ChooseClip(newClip, newClipIndex);
                this.Refresh();
            }
            return true;
        }

        public string[] GetAnimatedObjectNames()
        {
            string[] strArray = new string[this.animatedOptions.Length];
            for (int i = 0; i < strArray.Length; i++)
            {
                strArray[i] = this.animatedOptions[i].name;
            }
            return strArray;
        }

        public AnimationHierarchyData GetAnimationHierarchyData(FoldoutTree tree)
        {
            return new AnimationHierarchyData { animationWindow = this.m_AnimationWindow, animationSelection = this, states = tree.states };
        }

        private AnimationClip GetClipAtIndex(int index)
        {
            if (!this.hasAnimationComponent)
            {
                return null;
            }
            AnimationClip[] animationClips = AnimationUtility.GetAnimationClips(this.animatedObject.animation);
            if (index >= animationClips.Length)
            {
                return null;
            }
            return animationClips[index];
        }

        public string[] GetClipNames()
        {
            string[] strArray;
            if (this.hasAnimationComponent)
            {
                AnimationClip[] animationClips = AnimationUtility.GetAnimationClips(this.animatedObject.animation);
                strArray = new string[animationClips.Length + 2];
                for (int i = 0; i < animationClips.Length; i++)
                {
                    strArray[i] = CurveUtility.GetClipName(animationClips[i]);
                }
            }
            else
            {
                strArray = new string[1];
            }
            strArray[strArray.Length - 1] = "[Create New Clip]";
            return strArray;
        }

        private int GetIndexOfClip(AnimationClip clip)
        {
            if (this.hasAnimationComponent)
            {
                AnimationClip[] animationClips = AnimationUtility.GetAnimationClips(this.animatedObject.animation);
                for (int i = 0; i < animationClips.Length; i++)
                {
                    if (animationClips[i] == clip)
                    {
                        return i;
                    }
                }
            }
            return -1;
        }

        public static string GetObjectListHashCode(GameObject[] animatedOptions)
        {
            string[] array = new string[animatedOptions.Length];
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = animatedOptions[i].name;
            }
            return GetStringArrayHashCode(array);
        }

        public static string GetStringArrayHashCode(string[] array)
        {
            string str = string.Empty;
            foreach (string str2 in array)
            {
                str = str + "|" + str2;
            }
            return str;
        }

        public void OnGUIHierarchy(List<CurveState> shownProperties)
        {
            EditorGUI.indentLevel = 0;
            GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.ExpandWidth(true) };
            int width = (int) GUILayoutUtility.GetRect((float) 10f, (float) 0f, options).width;
            foreach (FoldoutTree tree in this.trees)
            {
                string goPath = string.Empty;
                if (this.animatedObject != null)
                {
                    goPath = AnimationUtility.CalculateTransformPath(tree.rootTransform, this.animatedObject.transform);
                }
                EditorGUI.indentLevel = 0;
                tree.root.OnGUI(this.GetAnimationHierarchyData(tree), goPath, 0, shownProperties);
            }
            if (this.m_LeftoverCurves.Count > 0)
            {
                AnimationWindow.vPosition += 5;
                Rect position = new Rect((float) ((width - 0x9b) / 2), (float) AnimationWindow.vPosition, 155f, 18f);
                if (GUI.Button(position, "Clean Up Leftover Curves"))
                {
                    AnimationCleanupPopup.Show(this.animatedObject, this.clip, this.m_LeftoverCurves, this.m_AnimationWindow);
                }
                AnimationWindow.vPosition += Mathf.RoundToInt(position.height);
            }
            AnimationWindow.vPosition += 15;
        }

        public static void OnGUISelection(AnimationSelection animSel, int width)
        {
            Rect position = new Rect(0f, 17f, (float) (width / 2), 15f);
            Rect rect2 = new Rect((float) (width / 2), 17f, (float) (width - (width / 2)), 15f);
            GUIStyle miniToolbarPopup = AnimationWindow.ms_Styles.miniToolbarPopup;
            if (animSel == null)
            {
                bool enabled = GUI.enabled;
                GUI.enabled = false;
                GUI.Label(position, string.Empty, miniToolbarPopup);
                GUI.Label(rect2, string.Empty, miniToolbarPopup);
                GUI.enabled = enabled;
            }
            else
            {
                animSel.m_ClipCanceled = false;
                bool flag2 = false;
                string[] animatedObjectNames = animSel.GetAnimatedObjectNames();
                int num = EditorGUI.Popup(position, animSel.m_AnimatedObjectIndex, animatedObjectNames, miniToolbarPopup);
                if (num != animSel.m_AnimatedObjectIndex)
                {
                    animSel.m_AnimatedObjectIndex = num;
                    animSel.animationWindow.chosenAnimated.Set(GetStringArrayHashCode(animatedObjectNames), animSel.m_AnimatedObjectIndex);
                    flag2 = true;
                    animSel.RefreshChosenClip(animSel.animationWindow.chosenClip);
                }
                string[] clipNames = animSel.GetClipNames();
                int clipIndex = animSel.clipIndex;
                int index = EditorGUI.Popup(rect2, clipIndex, clipNames, miniToolbarPopup);
                if (index != clipIndex)
                {
                    AnimationClip clipAtIndex = animSel.GetClipAtIndex(index);
                    if (clipAtIndex == null)
                    {
                        clipAtIndex = animSel.CreateNewClip(ref index);
                    }
                    if (clipAtIndex != null)
                    {
                        animSel.ChooseClip(clipAtIndex, index);
                        flag2 = true;
                    }
                }
                if (flag2)
                {
                    GUI.changed = true;
                    animSel.animationWindow.ReEnterAnimationMode();
                    animSel.Refresh();
                }
            }
        }

        public void Refresh()
        {
            this.SetAnimationCurves();
            foreach (FoldoutTree tree in this.trees)
            {
                tree.Refresh(this.GetAnimationHierarchyData(tree));
            }
            this.RefreshAutoRecordState();
        }

        public void RefreshAutoRecordState()
        {
            if (this.m_AnimationWindow.GetAutoRecordMode())
            {
                this.m_LastSampledState = AnimationPropertyDiff.ExtractCurrentState(this.animatedObject);
            }
            else
            {
                this.m_LastSampledState = null;
            }
        }

        private void RefreshChosenClip(SerializedStringTable chosenClip)
        {
            if (this.hasAnimationComponent)
            {
                string stringArrayHashCode = GetStringArrayHashCode(this.GetClipNames());
                if (!chosenClip.Contains(stringArrayHashCode))
                {
                    this.m_Clip = null;
                    if (this.animatedObject.animation.clip != null)
                    {
                        this.m_Clip = this.animatedObject.animation.clip;
                        chosenClip.Set(stringArrayHashCode, this.GetIndexOfClip(this.m_Clip));
                    }
                    else
                    {
                        AnimationClip[] animationClips = AnimationUtility.GetAnimationClips(this.animatedObject.animation);
                        for (int i = 0; i < animationClips.Length; i++)
                        {
                            if (animationClips[i] != null)
                            {
                                this.m_Clip = animationClips[i];
                                break;
                            }
                        }
                    }
                }
                else
                {
                    this.m_Clip = this.GetClipAtIndex(chosenClip.Get(stringArrayHashCode));
                }
            }
        }

        private void SetAnimationCurves()
        {
            this.m_AnimatedCurves = new Hashtable();
            this.m_AnimatedPaths = new Hashtable();
            this.m_LeftoverCurves = new Hashtable();
            if (this.clip != null)
            {
                foreach (AnimationClipCurveData data in AnimationUtility.GetAllCurves(this.clip, false))
                {
                    int num3;
                    int curveID = CurveUtility.GetCurveID(this.clip, data);
                    this.m_AnimatedCurves[curveID] = true;
                    if (!this.CheckIfPropertyExists(data))
                    {
                        this.m_LeftoverCurves[data] = data;
                        continue;
                    }
                    this.m_AnimatedPaths[CurveUtility.GetPathAndTypeID(data.path, data.type)] = true;
                    string path = data.path;
                Label_00BF:
                    num3 = path.GetHashCode();
                    if (!this.m_AnimatedPaths.Contains(num3))
                    {
                        this.m_AnimatedPaths[num3] = true;
                        if (path.Length != 0)
                        {
                            int length = path.LastIndexOf('/');
                            if (length > 0)
                            {
                                path = path.Substring(0, length);
                            }
                            else
                            {
                                path = string.Empty;
                            }
                            goto Label_00BF;
                        }
                    }
                }
            }
        }

        public GameObject ShownRoot()
        {
            if (this.trees.Length < 1)
            {
                return null;
            }
            return this.trees[0].rootGameObject;
        }

        public Hashtable animatedCurves
        {
            get
            {
                if (this.m_AnimatedCurves == null)
                {
                    this.SetAnimationCurves();
                }
                return this.m_AnimatedCurves;
            }
        }

        public GameObject animatedObject
        {
            get
            {
                return this.animatedOptions[this.m_AnimatedObjectIndex];
            }
        }

        public int animatedObjectIndex
        {
            get
            {
                return this.m_AnimatedObjectIndex;
            }
        }

        public GameObject[] animatedOptions
        {
            get
            {
                return this.m_AnimatedOptions;
            }
        }

        public Hashtable animatedPaths
        {
            get
            {
                if (this.m_AnimatedPaths == null)
                {
                    this.SetAnimationCurves();
                }
                return this.m_AnimatedPaths;
            }
        }

        public AnimationWindow animationWindow
        {
            get
            {
                return this.m_AnimationWindow;
            }
        }

        public bool CanClipAndGameObjectBeEdited
        {
            get
            {
                if (this.m_Clip == null)
                {
                    return false;
                }
                if ((this.m_Clip.hideFlags & HideFlags.NotEditable) != 0)
                {
                    return false;
                }
                return this.GameObjectIsAnimatable;
            }
        }

        public AnimationClip clip
        {
            get
            {
                return this.m_Clip;
            }
        }

        public int clipIndex
        {
            get
            {
                return this.GetIndexOfClip(this.m_Clip);
            }
        }

        public bool GameObjectIsAnimatable
        {
            get
            {
                if (this.animatedObject == null)
                {
                    return false;
                }
                if ((this.animatedObject.hideFlags & HideFlags.NotEditable) != 0)
                {
                    return false;
                }
                if (EditorUtility.IsPersistent(this.animatedObject))
                {
                    return false;
                }
                return true;
            }
        }

        public bool hasAnimationComponent
        {
            get
            {
                return (this.animatedObject.animation != null);
            }
        }

        public Hashtable leftoverCurves
        {
            get
            {
                return this.m_LeftoverCurves;
            }
        }

        public FoldoutTree[] trees
        {
            get
            {
                return this.m_Trees;
            }
        }
    }
}

